#include <iostream>
#include <string>
#include <fstream>
#include <iostream>
#include <limits>
#include <string>
#include <cstdio>
#include <boost/program_options.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/regex.hpp>
#include "get_arg.h"


// link with -lboost_filesystem-gcc -lboost_program_options-gcc
// program_options_helper.cpp



// my functions
#define DEBUG_LEVEL 6
#include <debug_func.h>
#include <print_error.h>
#include <program_options_helper.h>

using std::ofstream;
using std::ifstream;
using std::cout;
using std::string;
using std::vector;
using std::cerr;
using namespace program_options_helper;
namespace po = boost::program_options_lg;


//_______________________________________________________________________________________

//		process_command_line_options

//				from command line
//				Created [9/13/2001]

//_______________________________________________________________________________________



bool process_command_line_options(int argc, char* argv[], t_program_args& args)
{
	//
	//	Mandatory arguments
	//
	//po::options_description mandatory_args("Mandatory Arguments");
	//mandatory_args.add_options()


	//
	//	Positional arguments
	//
	//po::positional_options_description positional_parser;
	//positional_parser.add("input_files", -1);
    //
	//po::options_description positional_args("Positional Arguments");
	//positional_args.add_options()
	//("input_files,i",	po::value<vector<string> >(&args.input_files)
	//										->set_name("FILES"),
	//										"dnds results.");

	//
	//	Optional arguments
	//
	args.optional_args.add_options()
	("input_file,i",		po::value<string>(&args.file_input)
										->set_name("FILE")
										->default_value("STDIN"),
									"File containing pairwise distances.")
	("reciprocals,R",   	po::bool_switch(&args.reciprocals),
									"Repeat pairs if they are the best "
									"partners of each other.")
	("coverage,c",   		po::bool_switch(&args.coverage),
									"Take coverage into account (in the fourth column of "
									"the pairwise distance data). Full length or longer "
									"coverage always trumps fragmentary coverage.")
	("regex,r", 			po::value<string>(&args.regex)
										->default_value("(.*)")
										->set_name("REGEX"),
									"Regular expression to extract patterns.")
	("#comment,#",			po::value<string>(&args.comment_letters)
										->set_name("LETTERS")
										->default_value("#"),
									"Use one of these letters to begin a "
									"commented line.");
	
	args.add_std_options();

	//	Parse all arguments
	//
	po::options_description all_args("");
	all_args

				//	Mandatory arguments
				//.add(mandatory_args)

				//	Optional arguments
				.add(args.optional_args);

				//	Positional arguments
				//.add(positional_args);

	po::variables_map vm;
	po::store(po::command_line_parser(argc, argv)
								.options(all_args)

								//	Positional arguments
								// .positional(positional_parser)

								.run(), vm);
	po::notify(vm);


	if (vm.count("version"))
	{
		print_version(cerr, *argv, "1.2\n"
			"\tHistory: \n\n"
			"\tv 1.0\1"
			"07-09-2005\1"
			"Initial version\n"
			"\tv 1.1\1"
			"04-01-2006\1"
			"For Andreas: Hash start comment lines. Fix bugs in handling input. "
			"Upgrade to common code for sequence pair identifiers\n"
			"\tv 1.2\1"
			"27-03-2006\1"
			"Comments can begin with user-defined letters. Defaults to hash '#'\n"
			"\tv 1.3\1"
			"12-07-2006\1"
			"Ignore self-self matches\n"
			"\tv 1.4\1"
			"18-09-2006\1"
			"Add regular expression to extract the matching sub-part of each identifier.\n"
			);
		return false;
	}

	if (vm.count("help"))
	{
		string exe_description =
							"Takes a tab-delimited FILE with identifier pairs and their "
							"pair wise distance. For each identifier, find its partner "
							"with the smallest distance.\n"
							"The output is sent to STDOUT with the distance in the third column.\n"
							"If --reciprocals is specified, the first identifier in each pair "
							"will be unique . If two identifiers are the best pairs of each "
							"other, duplicated pairs will be printed.\n"
							"--regex is used to extract the part of the identifier to match."
							"The full identifier is used for output.";

		//
		//	Only output visible arguments for help string
		//
		po::options_description visible_args("");
		visible_args

					//	Mandatory arguments
					//.add(mandatory_args)

					//	Optional arguments
					.add(args.optional_args);


		print_usage(cerr, string(*argv),    "[OPTIONS] > LOWEST_PAIRS.dS ",
							visible_args, exe_description, 80);
		return false;
	}

	try
	{
		boost::regex try_regex(args.regex);
	}
	catch(std::exception& e)
	{
		throw std::runtime_error("Invalid regular expression specified in --regex:\n" +
										string(e.what()));
	}

	//
	// make sure regex surrounded by brackets
	//
	boost::regex brackets("\\(.*\\)");
	if (!boost::regex_search(args.regex, brackets))
	{
		std_print_warning("Missing brackets around the regular expression have been "
							"added back in.\n");
		args.regex = "(" + args.regex + ")";
	}


	args.open_err_log();
	return true;
}




